import time
import hashlib
import hmac
import base64
import uuid
from typing import Dict, Optional, Any
from abc import ABC, abstractmethod
import http_clients


class BaseAuthHandler(ABC):
    """认证处理器基类"""
    
    @abstractmethod
    def apply_auth(self, request_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        应用认证信息到请求数据
        
        参数:
            request_data: 包含headers、params等请求信息的字典
        返回:
            修改后的请求数据
        """
        pass


class BearerTokenHandler(BaseAuthHandler):
    """Bearer Token认证处理器"""
    
    def __init__(self, token: Optional[str] = None, token_getter: Optional[callable] = None):
        """
        初始化Bearer Token认证处理器
        
        参数:
            token: 静态token
            token_getter: 动态获取token的函数
        """
        self.token = token
        self.token_getter = token_getter
    
    def apply_auth(self, request_data: Dict[str, Any]) -> Dict[str, Any]:
        """应用Bearer Token认证"""
        token = self.token
        if self.token_getter:
            token = self.token_getter()
        
        if token:
            if 'headers' not in request_data:
                request_data['headers'] = {}
            request_data['headers']['Authorization'] = f'Bearer {token}'
        
        return request_data


class APISignatureHandler(BaseAuthHandler):
    """API签名认证处理器"""
    
    def __init__(self, app_id: str, app_secret: str, signature_method: str = 'HMAC-SHA256'):
        """
        初始化API签名认证处理器
        
        参数:
            app_id: 应用ID
            app_secret: 应用密钥
            signature_method: 签名方法
        """
        self.app_id = app_id
        self.app_secret = app_secret
        self.signature_method = signature_method
    
    def apply_auth(self, request_data: Dict[str, Any]) -> Dict[str, Any]:
        """应用API签名认证"""
        timestamp = str(int(time.time() * 1000))
        nonce = str(uuid.uuid4()).replace('-', '')
        
        # 构建签名字符串
        sign_params = {
            'app_id': self.app_id,
            'timestamp': timestamp,
            'nonce': nonce
        }
        
        # 添加请求参数到签名
        if 'params' in request_data and request_data['params']:
            sign_params.update(request_data['params'])
        
        # 对参数排序并构建查询字符串
        sorted_params = sorted(sign_params.items())
        query_string = '&'.join([f'{k}={v}' for k, v in sorted_params])
        
        # 生成签名
        signature = self._generate_signature(query_string)
        
        # 添加认证信息到请求头
        if 'headers' not in request_data:
            request_data['headers'] = {}
        
        request_data['headers'].update({
            'X-App-Id': self.app_id,
            'X-Timestamp': timestamp,
            'X-Nonce': nonce,
            'X-Signature': signature,
            'X-Signature-Method': self.signature_method
        })
        
        return request_data
    
    def _generate_signature(self, data: str) -> str:
        """生成签名"""
        if self.signature_method == 'HMAC-SHA256':
            signature = hmac.new(
                self.app_secret.encode('utf-8'),
                data.encode('utf-8'),
                hashlib.sha256
            ).hexdigest()
            return signature
        else:
            raise ValueError(f"不支持的签名方法: {self.signature_method}")


class OAuth2Handler(BaseAuthHandler):
    """OAuth2认证处理器"""
    
    def __init__(self, client_id: str, client_secret: str, token_url: str, 
                 access_token: Optional[str] = None, refresh_token: Optional[str] = None):
        """
        初始化OAuth2认证处理器
        
        参数:
            client_id: 客户端ID
            client_secret: 客户端密钥
            token_url: 获取token的URL
            access_token: 访问token
            refresh_token: 刷新token
        """
        self.client_id = client_id
        self.client_secret = client_secret
        self.token_url = token_url
        self.access_token = access_token
        self.refresh_token = refresh_token
        self.token_expires_at = 0
    
    def apply_auth(self, request_data: Dict[str, Any]) -> Dict[str, Any]:
        """应用OAuth2认证"""
        # 检查token是否过期，如果过期则刷新
        if self._is_token_expired():
            self._refresh_access_token()
        
        if self.access_token:
            if 'headers' not in request_data:
                request_data['headers'] = {}
            request_data['headers']['Authorization'] = f'Bearer {self.access_token}'
        
        return request_data
    
    def _is_token_expired(self) -> bool:
        """检查token是否过期"""
        return time.time() >= self.token_expires_at
    
    def _refresh_access_token(self):
        """刷新访问token"""
        if not self.refresh_token:
            return
        
        data = {
            'grant_type': 'refresh_token',
            'refresh_token': self.refresh_token,
            'client_id': self.client_id,
            'client_secret': self.client_secret
        }
        
        response = http_clients.post(self.token_url, data=data)
        if response.status_code == 200:
            token_data = response.json()
            self.access_token = token_data.get('access_token')
            expires_in = token_data.get('expires_in', 3600)
            self.token_expires_at = time.time() + expires_in
            if 'refresh_token' in token_data:
                self.refresh_token = token_data['refresh_token']


class MFATokenHandler(BaseAuthHandler):
    """多因素认证Token处理器"""
    
    def __init__(self, primary_token: str, mfa_code: str):
        """
        初始化MFA Token认证处理器
        
        参数:
            primary_token: 主要认证token
            mfa_code: 多因素认证码
        """
        self.primary_token = primary_token
        self.mfa_code = mfa_code
    
    def apply_auth(self, request_data: Dict[str, Any]) -> Dict[str, Any]:
        """应用MFA认证"""
        if 'headers' not in request_data:
            request_data['headers'] = {}
        
        request_data['headers'].update({
            'Authorization': f'Bearer {self.primary_token}',
            'X-MFA-Code': self.mfa_code
        })
        
        return request_data


class STSAuthHandler(BaseAuthHandler):
    """临时访问凭证认证处理器"""
    
    def __init__(self, access_key: str, secret_key: str, security_token: str, region: str = 'cn-north-1'):
        """
        初始化STS认证处理器
        
        参数:
            access_key: 访问密钥ID
            secret_key: 秘密访问密钥
            security_token: 安全令牌
            region: 区域
        """
        self.access_key = access_key
        self.secret_key = secret_key
        self.security_token = security_token
        self.region = region
    
    def apply_auth(self, request_data: Dict[str, Any]) -> Dict[str, Any]:
        """应用STS认证"""
        timestamp = time.strftime('%Y%m%dT%H%M%SZ', time.gmtime())
        
        if 'headers' not in request_data:
            request_data['headers'] = {}
        
        request_data['headers'].update({
            'X-Access-Key-Id': self.access_key,
            'X-Security-Token': self.security_token,
            'X-Timestamp': timestamp,
            'X-Region': self.region
        })
        
        return request_data


class CompositeAuthHandler(BaseAuthHandler):
    """组合认证处理器，支持多种认证方式组合"""
    
    def __init__(self, handlers: list):
        """
        初始化组合认证处理器
        
        参数:
            handlers: 认证处理器列表
        """
        self.handlers = handlers
    
    def apply_auth(self, request_data: Dict[str, Any]) -> Dict[str, Any]:
        """按顺序应用所有认证处理器"""
        for handler in self.handlers:
            request_data = handler.apply_auth(request_data)
        return request_data 